﻿using System.ComponentModel;
using System.ServiceModel.DomainServices.Client;
using ObservableCollections.Extensions;
using ObservableCollections.Interfaces;

namespace ObservableCollections
{
    /// <summary>
    /// this class is used to observe when an entity reference is changed and keeps the old reference
    /// It keeps track of changes on the currententity, and the original when it's not changed
    /// When rollingback the original entity is reverted back to it original state
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class ObservableEntity<T>:INotifyPropertyChanged where T:Entity
    {
        public ObservableEntity(T entity, ICollectionChanged parent)
        {
            _parent = parent;
           Entity= _originalEntity = entity;
            //for the first initialization it's clean record
            _parent.ClearDirty();
            if (entity != null)
                _entity.PropertyChanged += (s, e) => OnPropertyChanged(e.PropertyName);
        }

        private T _originalEntity;
        private T _entity;
        private ICollectionChanged _parent;

        public T Entity
        {
            get { return _entity; }
            set
            {
                _entity = value;
                if (_entity != null) 
                    _entity.PropertyChanged += (s, e) => OnPropertyChanged(e.PropertyName);
                OnPropertyChanged("Entity");
            }
        }

        public T OriginalEntity
        {
            get { return _originalEntity; }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            _parent.MarkDirty();
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        public void Undo()
        {
            _entity = _originalEntity;
            _originalEntity.Undo();
            if (_entity != null)
                _entity.PropertyChanged += (s, e) => OnPropertyChanged(e.PropertyName);
        }

        public void Reset()
        {
            var oe = _originalEntity as IObservableEntity;
            if(oe!=null )
                oe.CurrentEntitySet.Detach(_originalEntity);
            _entity = null;
            _originalEntity = null;
        }
    }
}
